שלטו ב-JavaScript Temporal API לטיפול מודרני בתאריך ובשעה. למדו כיצד להחליף אובייקטי Date מיושנים ב-API עוצמתי, אינטואיטיבי ומודע לאזורי זמן.
JavaScript Temporal API: טיפול מודרני בתאריך ובשעה
אובייקט ה-Date של JavaScript היה במשך זמן רב מקור לתסכול עבור מפתחים. יכולת השינוי שלו (mutability), היעדר תמיכה מובנית באזורי זמן, ו-API מסורבל הובילו לאינספור ספריות ופתרונות עוקפים. למרבה המזל, Temporal API שואף לטפל בחסרונות אלה, ומספק פתרון מודרני, אינטואיטיבי ומודע לאזורי זמן לטיפול בתאריך ובשעה ב-JavaScript.
מהו Temporal API?
Temporal API הוא אובייקט גלובלי חדש, Temporal, המספק דרך מודרנית וסטנדרטית לעבודה עם תאריכים וזמנים ב-JavaScript. הוא תוכנן להחליף את אובייקט ה-Date המיושן, ומציע שיפורים משמעותיים מבחינת עיצוב ה-API, אי-שינוי (immutability), תמיכה באזורי זמן, ושימושיות כוללת. הוא חלק מהצעת ECMAScript ונמצא ביישום במנועי JavaScript מרכזיים.
יתרונות עיקריים של Temporal API:
- אי-שינוי (Immutability): אובייקטים של Temporal הם בלתי ניתנים לשינוי (immutable), מה שאומר שפעולות עליהם מחזירות אובייקטים חדשים במקום לשנות את המקורי. זה עוזר למנוע תופעות לוואי בלתי צפויות והופך את הקוד לקל יותר להבנה.
- API ברור: ה-API תוכנן להיות אינטואיטיבי ועקבי יותר מאובייקט ה-
Dateהמיושן. - תמיכה באזורי זמן: Temporal מספק תמיכה חזקה באזורי זמן, ומאפשר לכם לעבוד עם תאריכים וזמנים במיקומים שונים ברחבי העולם.
- תמיכה בלוחות שנה: מעבר ללוח השנה הגרגוריאני, ה-API מאפשר שימוש במערכות לוחות שנה אחרות, מה שמקל על יישומים גלובליים.
- טיפול בשניות קפיצה (Leap Second): Temporal API מתחשב בשניות קפיצה, ומספק חישובי זמן מדויקים יותר.
תחילת עבודה עם Temporal
בעוד ש-Temporal API עדיין בפיתוח ולא נתמך באופן מלא בכל הדפדפנים וסביבות Node.js, ניתן להשתמש בפוליפיל (polyfill) כדי להתחיל להתנסות בו כבר היום. ניתן להתקין את הפוליפיל באמצעות npm:
npm install @js-temporal/polyfill
לאחר מכן, ייבאו את הפוליפיל בקוד ה-JavaScript שלכם:
import { Temporal } from '@js-temporal/polyfill';
לאחר שהפוליפיל מותקן, תוכלו להתחיל להשתמש באובייקט ה-Temporal ובמחלקות השונות שלו.
מחלקות הליבה של Temporal
Temporal API מספק מספר מחלקות מפתח לעבודה עם תאריכים וזמנים:
Temporal.PlainDate: מייצג תאריך לוח שנה (שנה, חודש ויום) ללא מידע על אזור זמן או שעת יום.Temporal.PlainTime: מייצג שעת יום (שעה, דקה, שנייה ושבריר שנייה) ללא מידע על תאריך או אזור זמן.Temporal.PlainDateTime: מייצג תאריך ושעה ללא מידע על אזור זמן.Temporal.ZonedDateTime: מייצג תאריך ושעה עם אזור זמן ספציפי.Temporal.Instant: מייצג נקודת זמן ספציפית, הנמדדת בננו-שניות מאז עידן יוניקס (1 בינואר 1970, בשעה 00:00:00 זמן אוניברסלי מתואם (UTC)).Temporal.TimeZone: מייצג אזור זמן.Temporal.Duration: מייצג משך זמן, כגון שעות, דקות או שניות.Temporal.Now: מספק גישה לתאריך ולשעה הנוכחיים.
עבודה עם PlainDate
המחלקה Temporal.PlainDate מייצגת תאריך ללא מידע על אזור זמן או שעת יום. היא שימושית לייצוג ימי הולדת, ימי נישואין או אירועים אחרים מבוססי תאריך.
יצירת PlainDate:
const plainDate = Temporal.PlainDate.from({ year: 2024, month: 10, day: 26 });
console.log(plainDate.toString()); // Output: 2024-10-26
ניתן גם ליצור PlainDate ממחרוזת בפורמט ISO 8601:
const plainDateFromString = Temporal.PlainDate.from('2024-12-25');
console.log(plainDateFromString.toString()); // Output: 2024-12-25
גישה לרכיבי תאריך:
const year = plainDate.year; // 2024
const month = plainDate.month; // 10
const day = plainDate.day; // 26
const dayOfWeek = plainDate.dayOfWeek; // Day of the week (1-7, Monday-Sunday)
const dayOfYear = plainDate.dayOfYear; // Day of the year (1-366)
const daysInMonth = plainDate.daysInMonth; // Number of days in the month
const isLeapYear = plainDate.isLeapYear; // Boolean indicating if the year is a leap year
הוספה והחסרה של ימים:
const nextDay = plainDate.add({ days: 1 });
console.log(nextDay.toString()); // Output: 2024-10-27
const previousWeek = plainDate.subtract({ weeks: 1 });
console.log(previousWeek.toString()); // Output: 2024-10-19
השוואת תאריכים:
const anotherDate = Temporal.PlainDate.from({ year: 2024, month: 11, day: 15 });
if (plainDate.equals(anotherDate)) {
console.log('Dates are equal');
} else if (plainDate.lessThan(anotherDate)) {
console.log('plainDate is earlier than anotherDate');
} else {
console.log('plainDate is later than anotherDate');
}
// Output: plainDate is earlier than anotherDate
עבודה עם PlainTime
המחלקה Temporal.PlainTime מייצגת שעת יום ללא מידע על תאריך או אזור זמן. היא שימושית לייצוג שעות פתיחה, זמני פגישות או אירועים אחרים מבוססי זמן.
יצירת PlainTime:
const plainTime = Temporal.PlainTime.from({ hour: 14, minute: 30, second: 0 });
console.log(plainTime.toString()); // Output: 14:30:00
ניתן גם ליצור PlainTime ממחרוזת בפורמט ISO 8601:
const plainTimeFromString = Temporal.PlainTime.from('09:00:00');
console.log(plainTimeFromString.toString()); // Output: 09:00:00
גישה לרכיבי זמן:
const hour = plainTime.hour; // 14
const minute = plainTime.minute; // 30
const second = plainTime.second; // 0
const millisecond = plainTime.millisecond; // 0
const microsecond = plainTime.microsecond; // 0
const nanosecond = plainTime.nanosecond; // 0
הוספה והחסרה של זמן:
const laterTime = plainTime.add({ minutes: 15 });
console.log(laterTime.toString()); // Output: 14:45:00
const earlierTime = plainTime.subtract({ hours: 1 });
console.log(earlierTime.toString()); // Output: 13:30:00
השוואת זמנים:
const anotherTime = Temporal.PlainTime.from({ hour: 15, minute: 0, second: 0 });
if (plainTime.equals(anotherTime)) {
console.log('Times are equal');
} else if (plainTime.lessThan(anotherTime)) {
console.log('plainTime is earlier than anotherTime');
} else {
console.log('plainTime is later than anotherTime');
}
// Output: plainTime is earlier than anotherTime
עבודה עם PlainDateTime
המחלקה Temporal.PlainDateTime מייצגת תאריך ושעה ללא מידע על אזור זמן. היא משלבת את הפונקציונליות של PlainDate ו-PlainTime.
יצירת PlainDateTime:
const plainDateTime = Temporal.PlainDateTime.from({ year: 2024, month: 10, day: 26, hour: 14, minute: 30, second: 0 });
console.log(plainDateTime.toString()); // Output: 2024-10-26T14:30:00
ניתן גם ליצור PlainDateTime ממחרוזת בפורמט ISO 8601:
const plainDateTimeFromString = Temporal.PlainDateTime.from('2024-12-25T09:00:00');
console.log(plainDateTimeFromString.toString()); // Output: 2024-12-25T09:00:00
גישה לרכיבי תאריך ושעה:
const year = plainDateTime.year; // 2024
const month = plainDateTime.month; // 10
const day = plainDateTime.day; // 26
const hour = plainDateTime.hour; // 14
const minute = plainDateTime.minute; // 30
const second = plainDateTime.second; // 0
הוספה והחסרה של תאריכים וזמנים:
const nextDayAndTime = plainDateTime.add({ days: 1, hours: 2 });
console.log(nextDayAndTime.toString()); // Output: 2024-10-27T16:30:00
const previousWeekAndTime = plainDateTime.subtract({ weeks: 1, minutes: 30 });
console.log(previousWeekAndTime.toString()); // Output: 2024-10-19T14:00:00
המרת ל-PlainDate ו-PlainTime:
const plainDateFromDateTime = plainDateTime.toPlainDate();
console.log(plainDateFromDateTime.toString()); // Output: 2024-10-26
const plainTimeFromDateTime = plainDateTime.toPlainTime();
console.log(plainTimeFromDateTime.toString()); // Output: 14:30:00
עבודה עם ZonedDateTime
המחלקה Temporal.ZonedDateTime מייצגת תאריך ושעה עם אזור זמן ספציפי. זה קריטי עבור יישומים שצריכים לטפל בתאריכים ובזמנים במיקומים שונים ברחבי העולם. בניגוד לאובייקט ה-Date המיושן, Temporal מספק תמיכה מובנית באזורי זמן.
יצירת ZonedDateTime:
const zonedDateTime = Temporal.ZonedDateTime.from({ year: 2024, month: 10, day: 26, hour: 14, minute: 30, second: 0, timeZone: 'America/Los_Angeles' });
console.log(zonedDateTime.toString()); // Output: 2024-10-26T14:30:00-07:00[America/Los_Angeles]
ניתן גם ליצור ZonedDateTime מ-Instant ואזור זמן:
const instant = Temporal.Instant.fromEpochSeconds(1666785000); // Example timestamp
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO('Europe/London');
console.log(zonedDateTimeFromInstant.toString()); // Output will vary based on the actual instant but will reflect the date/time in Europe/London
גישה לרכיבי תאריך ושעה:
const year = zonedDateTime.year; // 2024
const month = zonedDateTime.month; // 10
const day = zonedDateTime.day; // 26
const hour = zonedDateTime.hour; // 14
const minute = zonedDateTime.minute; // 30
const second = zonedDateTime.second; // 0
const timeZone = zonedDateTime.timeZone; // Temporal.TimeZone object
המרת בין אזורי זמן:
const newYorkDateTime = zonedDateTime.withTimeZone('America/New_York');
console.log(newYorkDateTime.toString()); // Output: 2024-10-26T17:30:00-04:00[America/New_York]
טיפול בשעון קיץ (DST):
Temporal מטפל אוטומטית במעברי DST. בעת הוספה או החסרה של זמן, הוא לוקח בחשבון את DST, ומבטיח תוצאות מדויקות. לדוגמה, שקלו פגישה המתוזמנת על פני מעבר ה-DST בגרמניה:
const meetingStart = Temporal.ZonedDateTime.from({ year: 2024, month: 3, day: 31, hour: 2, minute: 30, timeZone: 'Europe/Berlin' });
const meetingEnd = meetingStart.add({ hours: 1 }); // Adding 1 hour
console.log(meetingEnd.toString()); // Output: 2024-03-31T03:30:00+02:00[Europe/Berlin]. Notice the offset changes due to DST
עבודה עם Instant
המחלקה Temporal.Instant מייצגת נקודת זמן ספציפית, הנמדדת בננו-שניות מאז עידן יוניקס. היא שימושית לאחסון והשוואת רגעים מדויקים בזמן.
יצירת Instant:
const instant = Temporal.Instant.fromEpochSeconds(1666785000); // Example Unix timestamp in seconds
console.log(instant.toString()); // Output will be an ISO string representation of that instant
המרת ל-ZonedDateTime:
const zonedDateTimeFromInstant = instant.toZonedDateTimeISO('America/Los_Angeles');
console.log(zonedDateTimeFromInstant.toString()); // Output: Date and time in America/Los_Angeles corresponding to the instant
השוואת Instants:
const anotherInstant = Temporal.Instant.fromEpochSeconds(1666790000);
if (instant.equals(anotherInstant)) {
console.log('Instants are equal');
} else if (instant.lessThan(anotherInstant)) {
console.log('instant is earlier than anotherInstant');
} else {
console.log('instant is later than anotherInstant');
}
// Output: instant is earlier than anotherInstant
עבודה עם Duration
המחלקה Temporal.Duration מייצגת משך זמן, כגון שעות, דקות או שניות. היא שימושית לחישוב ההפרש בין שני תאריכים או זמנים.
יצירת Duration:
const duration = Temporal.Duration.from({ hours: 2, minutes: 30 });
console.log(duration.toString()); // Output: PT2H30M
חישוב ההפרש בין תאריכים/זמנים:
const startDate = Temporal.PlainDateTime.from({ year: 2024, month: 1, day: 1, hour: 0, minute: 0, second: 0 });
const endDate = Temporal.PlainDateTime.from({ year: 2024, month: 1, day: 3, hour: 12, minute: 30, second: 0 });
const difference = endDate.since(startDate);
console.log(difference.toString()); // Output: P2DT12H30M
// Accessing the components of the duration
console.log(difference.days); // 2
console.log(difference.hours); // 12
console.log(difference.minutes); // 30
הוספת Duration לתאריכים/זמנים:
const newDate = startDate.add(duration);
console.log(newDate.toString()); // Output: 2024-01-03T02:30:00
עבודה עם לוחות שנה
Temporal API תומך במערכות לוחות שנה שונות מעבר ללוח השנה הגרגוריאני. למרות שזה עדיין לא מיושם במלואו בכל הפוליפילים והמנועים, הכוונה היא לאפשר ליישומים לטפל בתאריכים בלוחות שנה ספציפיים לתרבויות שונות. לדוגמה, כדי להשתמש בלוח השנה היפני (היפותטית, שכן היישום עדיין מתפתח):
// This is a conceptual example as calendar support is still under development
// const japaneseDate = Temporal.PlainDate.from({ year: 2024, month: 10, day: 26, calendar: 'japanese' });
// console.log(japaneseDate.toString()); // Expected: Output formatted according to the Japanese calendar
הערה: תמיכה בלוחות שנה היא תכונה מתפתחת של Temporal API, ופונקציונליות מלאה עדיין אינה זמינה באופן גלובלי.
דוגמאות מעשיות ומקרי שימוש
Temporal API מציע מגוון רחב של אפשרויות לטיפול בתאריכים וזמנים ב-JavaScript. הנה כמה דוגמאות מעשיות ומקרי שימוש:
- תזמון פגישות: צרו יישום תזמון המאפשר למשתמשים לקבוע פגישות באזור הזמן המקומי שלהם.
Temporal.ZonedDateTimeמקל על המרה בין אזורי זמן וטיפול במעברי DST. עבור מרפאה בברלין המתזמנת פגישות גלובליות: - חישוב גיל: קבעו את גילו של משתמש בהתבסס על תאריך לידתו.
PlainDateמאפשר לכם לייצג את תאריך הלידה ללא כל מידע על אזור זמן. - הצגת תאריכים וזמנים בפורמטים שונים: עצבו תאריכים וזמנים לפי לוקאל המשתמש. בעוד שתכונות הבינלאומיות (Intl) נפרדות, ניתן לעצב אובייקטי Temporal בקלות באמצעות
toLocaleString()או שיטות דומות בשילוב עם תכונות Intl API. - מעקב אחר משכי אירועים: חשבו את משך אירוע והציגו אותו בפורמט קריא אנושית.
Durationמאפשר לכם לייצג את הפרש הזמן בין שני תאריכים או זמנים.
const appointmentTimeBerlin = Temporal.ZonedDateTime.from({ year: 2024, month: 11, day: 5, hour: 10, minute: 0, timeZone: 'Europe/Berlin' });
const appointmentTimeLA = appointmentTimeBerlin.withTimeZone('America/Los_Angeles');
console.log(`Appointment Time in Berlin: ${appointmentTimeBerlin.toString()}`);
console.log(`Appointment Time in Los Angeles: ${appointmentTimeLA.toString()}`);
const birthDate = Temporal.PlainDate.from({ year: 1990, month: 5, day: 15 });
const today = Temporal.Now.plainDateISO();
const age = today.year - birthDate.year - (today.month < birthDate.month || (today.month === birthDate.month && today.day < birthDate.day) ? 1 : 0);
console.log(`Age: ${age}`);
const zonedDateTimeNow = Temporal.Now.zonedDateTimeISO('en-GB');
console.log(zonedDateTimeNow.toLocaleString('en-GB'));
console.log(zonedDateTimeNow.toLocaleString('de-DE'));
const eventStart = Temporal.Instant.fromEpochSeconds(1700000000); // Example start timestamp
const eventEnd = Temporal.Instant.fromEpochSeconds(1700005000); // Example end timestamp
const durationOfEvent = eventEnd.since(eventStart);
console.log(`Event duration: ${durationOfEvent.minutes} minutes`);
שיטות עבודה מומלצות לשימוש ב-Temporal API
הנה כמה שיטות עבודה מומלצות שכדאי לזכור בעת השימוש ב-Temporal API:
- השתמשו באי-שינוי (Immutability): אמצו את תכונת אי-השינוי של אובייקטי Temporal. הימנעו משינוי אובייקטים ישירות. במקום זאת, צרו אובייקטים חדשים באמצעות שיטות כמו
add,subtractו-with. - טפלו באזורי זמן בזהירות: היו מודעים לאזורי זמן בעת עבודה עם תאריכים וזמנים. השתמשו ב-
ZonedDateTimeכאשר אתם צריכים לייצג תאריכים וזמנים באזור זמן ספציפי. - השתמשו בשמות משתנים ברורים: השתמשו בשמות משתנים תיאוריים המצביעים בבירור על סוג אובייקט Temporal שבו נעשה שימוש (לדוגמה,
plainDate,zonedDateTime,duration). - שקלו פוליפילים: מכיוון ש-Temporal עדיין חדש יחסית, ודאו תמיכה מספקת על ידי שימוש בספריית פוליפיל היכן שנדרש.
- אמתו קלט: אמתו תמיד קלט משתמש כדי לוודא שתאריכים וזמנים בפורמט הנכון.
הגירה מ-Legacy Date
ההגירה מאובייקט ה-Date המיושן יכולה להיות תהליך הדרגתי. שקלו את האסטרטגיות הבאות:
- אימוץ הדרגתי: התחילו להשתמש ב-Temporal בקוד חדש תוך שמירה על
Dateבחלקים קיימים של היישום שלכם. - פונקציות עוטפות (Wrapper Functions): צרו פונקציות עוטפות הממירות בין אובייקטי
Dateו-Temporal כדי להקל על יכולת הפעולה ההדדית במהלך ההגירה. - בדיקות יסודיות: בדקו את ההגירה באופן יסודי כדי לוודא שכל חישובי התאריך והשעה מדויקים.
Temporal API מול Moment.js
Moment.js הייתה ספרייה פופולרית לטיפול בתאריך ובשעה ב-JavaScript, אך היא נחשבת כיום לפרויקט מיושן ונמצאת במצב תחזוקה. Temporal API מספק פתרון מודרני וסטנדרטי יותר, המטפל ברבים מחסרונותיה של Moment.js. Moment.js ניתנת לשינוי וחסרה תמיכה מקורית באזורי זמן. Temporal API הוא בלתי ניתן לשינוי ויש לו תמיכה מקורית באזורי זמן.
סיכום
JavaScript Temporal API מייצג שיפור משמעותי לעומת אובייקט ה-Date המיושן. יכולת אי-השינוי שלו, ה-API הברור, התמיכה באזורי זמן, והתמיכה בלוחות שנה הופכים אותו לכלי עוצמתי לטיפול בתאריכים וזמנים ביישומי JavaScript מודרניים. בעוד שהאימוץ עדיין גדל, שימוש בפוליפיל מאפשר לכם להתחיל למנף את יתרונותיו כבר היום. ככל שה-API יהפוך נתמך יותר באופן נרחב, הוא צפוי להפוך לדרך הסטנדרטית לעבודה עם תאריכים וזמנים ב-JavaScript.
אמצו את Temporal API ופתחו דרך יעילה ואמינה יותר לנהל תאריכים וזמנים בפרויקטים שלכם, כדי להבטיח שהיישום שלכם מטפל באזורי זמן גלובליים ובחישובים בצורה מדויקת.